/**
 * WebSocket 日志记录工具
 * 用于追踪WebSocket连接状态、消息传输和错误信息
 */

interface LogEntry {
  timestamp: string
  level: 'INFO' | 'WARN' | 'ERROR' | 'DEBUG'
  category: 'CONNECTION' | 'MESSAGE' | 'HEARTBEAT' | 'RECONNECT' | 'ERROR' | 'NETWORK' | 'CXT'
  message: string
  data?: any
  url?: string
  readyState?: number
  networkStatus?: boolean
}

interface LogConfig {
  maxLogSize: number // 最大日志条数
  maxFileSize: number // 最大文件大小 (MB)
  enableConsole: boolean // 是否输出到控制台
  enableFile: boolean // 是否保存到文件
  logLevel: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' // 日志级别
}

class WebSocketLogger {
  private logs: LogEntry[] = []
  private config: LogConfig = {
    maxLogSize: 1000,
    maxFileSize: 10,
    enableConsole: true,
    enableFile: true,
    logLevel: 'DEBUG'
  }

  constructor(config?: Partial<LogConfig>) {
    if (config) {
      this.config = { ...this.config, ...config }
    }
  }

  /**
   * 记录日志
   */
  private log(level: LogEntry['level'], category: LogEntry['category'], message: string, data?: any, additionalInfo?: any): void {
    const entry: LogEntry = {
      timestamp: new Date().toISOString(),
      level,
      category,
      message,
      data,
      ...additionalInfo
    }

    // 检查日志级别
    if (!this.shouldLog(level)) {
      return
    }

    // 添加到内存日志
    this.logs.push(entry)

    // 控制台输出
    if (this.config.enableConsole) {
      this.logToConsole(entry)
    }

    // 文件输出
    if (this.config.enableFile) {
      this.logToFile(entry)
    }

    // 清理旧日志
    this.cleanupLogs()
  }

  /**
   * 检查是否应该记录此级别的日志
   */
  private shouldLog(level: LogEntry['level']): boolean {
    const levels = ['DEBUG', 'INFO', 'WARN', 'ERROR']
    const currentLevelIndex = levels.indexOf(this.config.logLevel)
    const logLevelIndex = levels.indexOf(level)
    return logLevelIndex >= currentLevelIndex
  }

  /**
   * 控制台输出
   */
  private logToConsole(entry: LogEntry): void {
    const prefix = `[WS-${entry.category}] ${entry.timestamp}`
    const style = this.getConsoleStyle(entry.level)
    
    console.group(`%c${prefix}`, style)
    console.log(`%c${entry.message}`, 'color: #333; font-weight: bold;')
    
    if (entry.data) {
      console.log('Data:', entry.data)
    }
    
    if (entry.url) {
      console.log('URL:', entry.url)
    }
    
    if (entry.readyState !== undefined) {
      console.log('ReadyState:', this.getReadyStateText(entry.readyState))
    }
    
    if (entry.networkStatus !== undefined) {
      console.log('Network:', entry.networkStatus ? 'Online' : 'Offline')
    }
    
    console.groupEnd()
  }

  /**
   * 获取控制台样式
   */
  private getConsoleStyle(level: LogEntry['level']): string {
    const styles = {
      DEBUG: 'color: #666; font-size: 12px;',
      INFO: 'color: #2196F3; font-weight: bold;',
      WARN: 'color: #FF9800; font-weight: bold;',
      ERROR: 'color: #F44336; font-weight: bold;'
    }
    return styles[level]
  }

  /**
   * 获取WebSocket状态文本
   */
  private getReadyStateText(readyState: number): string {
    const states = {
      0: 'CONNECTING',
      1: 'OPEN',
      2: 'CLOSING',
      3: 'CLOSED'
    }
    return states[readyState as keyof typeof states] || 'UNKNOWN'
  }

  /**
   * 文件输出
   */
  private logToFile(entry: LogEntry): void {
    try {
      const logLine = this.formatLogLine(entry)
      
      // 在Electron环境中保存到文件
      if ((window as any).system?.writeWsLog) {
        (window as any).system.writeWsLog(logLine)
      } else {
        // 浏览器环境使用localStorage作为备用
        this.saveToLocalStorage(logLine)
      }
    } catch (error) {
      console.error('Failed to write log to file:', error)
    }
  }

  /**
   * 格式化日志行
   */
  private formatLogLine(entry: LogEntry): string {
    const parts = [
      entry.timestamp,
      entry.level,
      entry.category,
      entry.message
    ]

    if (entry.data) {
      parts.push(`DATA:${JSON.stringify(entry.data)}`)
    }

    if (entry.url) {
      parts.push(`URL:${entry.url}`)
    }

    if (entry.readyState !== undefined) {
      parts.push(`STATE:${entry.readyState}`)
    }

    if (entry.networkStatus !== undefined) {
      parts.push(`NET:${entry.networkStatus}`)
    }

    return parts.join(' | ')
  }

  /**
   * 保存到localStorage（浏览器环境备用）
   */
  private saveToLocalStorage(logLine: string): void {
    try {
      const key = 'ws_logs'
      const existingLogs = localStorage.getItem(key) || ''
      const newLogs = existingLogs + logLine + '\n'
      
      // 限制localStorage大小
      if (newLogs.length > 100000) { // 100KB限制
        const lines = newLogs.split('\n')
        const recentLines = lines.slice(-500) // 保留最近500行
        localStorage.setItem(key, recentLines.join('\n'))
      } else {
        localStorage.setItem(key, newLogs)
      }
    } catch (error) {
      console.error('Failed to save log to localStorage:', error)
    }
  }

  /**
   * 清理旧日志
   */
  private cleanupLogs(): void {
    if (this.logs.length > this.config.maxLogSize) {
      this.logs = this.logs.slice(-this.config.maxLogSize)
    }
  }

  // 公共日志方法
  info(category: LogEntry['category'], message: string, data?: any, additionalInfo?: any): void {
    this.log('INFO', category, message, data, additionalInfo)
  }

  warn(category: LogEntry['category'], message: string, data?: any, additionalInfo?: any): void {
    this.log('WARN', category, message, data, additionalInfo)
  }

  error(category: LogEntry['category'], message: string, data?: any, additionalInfo?: any): void {
    this.log('ERROR', category, message, data, additionalInfo)
  }

  debug(category: LogEntry['category'], message: string, data?: any, additionalInfo?: any): void {
    this.log('DEBUG', category, message, data, additionalInfo)
  }

  /**
   * 获取所有日志
   */
  getLogs(): LogEntry[] {
    return [...this.logs]
  }

  /**
   * 获取指定类型的日志
   */
  getLogsByCategory(category: LogEntry['category']): LogEntry[] {
    return this.logs.filter(log => log.category === category)
  }

  /**
   * 获取错误日志
   */
  getErrorLogs(): LogEntry[] {
    return this.logs.filter(log => log.level === 'ERROR')
  }

  /**
   * 清空日志
   */
  clearLogs(): void {
    this.logs = []
  }

  /**
   * 导出日志
   */
  exportLogs(): string {
    return this.logs.map(entry => this.formatLogLine(entry)).join('\n')
  }

  /**
   * 更新配置
   */
  updateConfig(config: Partial<LogConfig>): void {
    this.config = { ...this.config, ...config }
  }
}

// 创建全局实例
export const wsLogger = new WebSocketLogger({
  enableConsole: true,
  enableFile: true,
  logLevel: 'DEBUG'
})

// 导出类型和类
export type { LogEntry, LogConfig }
export { WebSocketLogger }
